#![windows_subsystem = "windows"]

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use winapi::um::winuser::{GetForegroundWindow, GetWindowTextLengthW, GetWindowTextW};
use ws::{listen, Handler, Sender, Handshake, Message, CloseCode};
use std::sync::mpsc;
use tray_item::{IconSource, TrayItem};

enum Signal {
    Quit
}

struct Server {
    out: Sender,
    last_title: Arc<Mutex<String>>,
}

impl Handler for Server {
    fn on_open(&mut self, _: Handshake) -> ws::Result<()> {
        let last_title = self.last_title.clone();
        let out = self.out.clone();
        thread::spawn(move || {
            let mut local_last_title = String::new();
            loop {
                let title = get_active_window_title().unwrap_or_default();
                if local_last_title != title {
                    out.send(Message::text(format!("Title: {}", title))).unwrap();
                    local_last_title = title.clone();
                    let mut last_title = last_title.lock().unwrap();
                    *last_title = title;
                }

                thread::sleep(Duration::from_millis(100));
            }
        });
        Ok(())
    }

    fn on_close(&mut self, _: CloseCode, _: &str) {
        println!("Connection closed");
    }
}

fn get_active_window_title() -> Option<String> {
    unsafe {
        let hwnd = GetForegroundWindow();
        if hwnd.is_null() {
            return None;
        }

        let length = GetWindowTextLengthW(hwnd);
        if length == 0 {
            return None;
        }

        let mut buf = Vec::with_capacity((length + 1) as usize);
        let len = GetWindowTextW(hwnd, buf.as_mut_ptr(), length + 1);
        if len == 0 {
            return None;
        }
        buf.set_len(len as usize);
        Some(OsString::from_wide(&buf).to_string_lossy().into_owned())
    }
}

fn main() {
    let last_title = Arc::new(Mutex::new(String::new()));

    let mut tray = TrayItem::new(
        "zebarws",
        IconSource::Resource("tray-default"),
    )
    .unwrap();


    // tray.inner_mut().add_separator().unwrap();

    let (tx, rx) = mpsc::sync_channel(1);

    let red_tx = tx.clone();
    tray.add_menu_item("Quit", move || {
        red_tx.send(Signal::Quit).unwrap();
    })
    .unwrap();



    let last_title_clone = last_title.clone();
    thread::spawn(move || {
        listen("127.0.0.1:8080", |out| Server {
            out,
            last_title: last_title_clone.clone(),
        }).unwrap();
    });

    loop {
        match rx.recv() {
            Ok(Signal::Quit) => {
                println!("Quit");
                break;
            }
            _ => {}
        }
    }
}
